package worker

import (
	"context"
	"errors"
	"fmt"
	"time"

	"zhonghui/console/structs"
	"zhonghui/console/warehouse/dbx"
	"zhonghui/console/warehouse/dbx/cache_main"
	"zhonghui/console/warehouse/dbx/db_zh_kernel"
	"zhonghui/console/warehouse/dbx/db_zh_kernel_slave"
	"zhonghui/console/warehouse/logx"
	"zhonghui/console/warehouse/modelx/model_zh_kernel"
)

// TaskCompleteWorker 检测进行中的任务，置为完成
type TaskCompleteWorker struct {
}

func (w *TaskCompleteWorker) Start() {
	w.do()
	t := time.NewTicker(10 * time.Second)
	for {
		select {
		case <-t.C:
			w.do()
		}
	}
}

func (w *TaskCompleteWorker) do() {
	defer func() {
		if r := recover(); r != nil {
			logx.Zap().Errorw("定时任务异常", "err", errors.New(fmt.Sprintf("%s", r)))
		}
	}()

	rc := cache_main.Client()
	lock, ch, err := dbx.GetRedisLockWithRefresh(rc, dbx.RedisPrefix("locker-TaskCompleteWorker"), 5*time.Second, time.Second)
	if err != nil {
		return
	}
	defer func() {
		if ch != nil {
			ch <- 1
		}
		_ = lock.Release(context.Background())
	}()

	// 查询进行中的任务，和暂停的任务
	tasks := make([]model_zh_kernel.SysTask, 0)
	db_zh_kernel_slave.Client().Where("status in ?", []string{structs.TaskStatusProcessing, structs.TaskStatusPaused}).Find(&tasks)

	type result struct {
		Total  int64
		Status string
	}

	for _, task := range tasks {
		// 快速判断一下结束
		if db_zh_kernel_slave.Client().Where("task_id = ? and status in ?", task.ID, []string{"", "queue", "prepared"}).Take(&model_zh_kernel.SysSmsRecord{}).Error == nil {
			continue
		}

		// 汇总统计
		res := make([]result, 0)
		db_zh_kernel_slave.Client().Model(&model_zh_kernel.SysSmsRecord{}).
			Where("task_id = ?", task.ID).
			Group("status").
			Select("count(1) as total, status").
			Find(&res)

		var total, success, fail uint64
		for _, r := range res {
			switch r.Status {
			case "":
			case "queue", "prepared":
			case "fail":
				fail++
			default:
				success++
			}

			total++
		}

		if success+fail == total {
			task.Status = structs.TaskStatusCompleted
			task.CountSuccess = success
			task.CountFail = fail
			if err := db_zh_kernel.Client().Save(&task).Error; err != nil {
				logx.Zap().Errorw("更新任务状态失败", "err", err)
			}
		}
	}
}
